package com.yc.tools;

import java.math.BigDecimal;

import static java.lang.Math.*;

/**
 * 坐标转换util
 *
 * @author: zz
 * @date: 2018/12/7 14:29
 */
public class PositionConvertUtil {

    private static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;

    /**
     * 对double类型数据保留小数点后多少位
     * 高德地图转码返回的就是 小数点后6位，为了统一封装一下
     *
     * @param digit 位数
     * @param in    输入
     * @return 保留小数位后的数
     */
    private static double dataDigit(int digit, double in) {
        return BigDecimal.valueOf(in).setScale(digit, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    private static String dataDigitToStr(int digit, double in) {
        return BigDecimal.valueOf(in).setScale(digit, BigDecimal.ROUND_HALF_UP).toString();
    }

    /**
     * 将火星坐标转变成百度坐标（高德、腾讯地图坐标等）
     *
     * @param lngStr 经度
     * @param latStr 纬度
     * @return 百度坐标, 经纬度，逗号隔开
     */

    public static String gdConvertBd(String lngStr, String latStr) {
        double lng = Double.valueOf(lngStr), lat = Double.valueOf(latStr);
        double[] doubles = gdConvertBd(lng, lat);
        return doubles[0] + "," + doubles[1];
    }

    public static String[] gdConvertBdRetStr(String lngStr, String latStr) {
        double lng = Double.valueOf(lngStr), lat = Double.valueOf(latStr);
        double[] doubles = gdConvertBd(lng, lat);
        return new String[]{String.valueOf(doubles[0]), String.valueOf(doubles[1])};
    }

    public static double[] gdConvertBd(double lng, double lat) {
        double z = sqrt(lng * lng + lat * lat) + 0.00002 * sin(lat * x_pi);
        double theta = atan2(lat, lng) + 0.000003 * cos(lng * x_pi);
        return new double[]{dataDigit(6, z * cos(theta) + 0.0065), dataDigit(6, z * sin(theta) + 0.006)};
    }

    /**
     * 将百度坐标转变成火星坐标(高德 、 腾讯地图等)
     *
     * @param lngStr 经度
     * @param latStr 纬度
     * @return 火星坐标, 经纬度，逗号隔开
     */
    public static String bdConvertGd(String lngStr, String latStr) {
        double lng = Double.valueOf(lngStr), lat = Double.valueOf(latStr);
        double[] doubles = bdConvertGd(lng, lat);
        return doubles[0] + "," + doubles[1];
    }

    public static String bdConvertGd(String lngStr, String latStr, int digit) {
        double lng = Double.valueOf(lngStr), lat = Double.valueOf(latStr);
        double[] doubles = bdConvertGd(lng, lat);
        return dataDigitToStr(digit, doubles[0]) + "," + dataDigitToStr(digit, doubles[1]);
    }

    public static String[] bdConvertGdRetStr(String lngStr, String latStr) {
        double lng = Double.valueOf(lngStr), lat = Double.valueOf(latStr);
        double[] doubles = bdConvertGd(lng, lat);
        return new String[]{String.valueOf(doubles[0]), String.valueOf(doubles[1])};
    }

    public static double[] bdConvertGd(double lng, double lat) {
        double x = lng - 0.0065, y = lat - 0.006;
        double z = sqrt(x * x + y * y) - 0.00002 * sin(y * x_pi);
        double theta = atan2(y, x) - 0.000003 * cos(x * x_pi);
        return new double[]{dataDigit(6, z * cos(theta)), dataDigit(6, z * sin(theta))};
    }

    /**
     * 已知一个坐标点和最大距离，求另一坐标的区域范围【大致计算，不精确，慎用】
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @param dis       距离
     * @return [maxlng,minlng,maxlat,minlat]
     */
    private static final double EARTH_R = 6371000;//地球半径米
    public static String[] findNeighPosition(double longitude, double latitude, int dis) {
        //先计算查询点的经纬度范围
        double dlng = 2 * Math.asin(Math.sin(dis / (2 * EARTH_R)) / Math.cos(latitude * Math.PI / 180));
        dlng = dlng * 180 / Math.PI;//角度转为弧度
        double dlat = dis / EARTH_R;
        dlat = dlat * 180 / Math.PI;
        double minlat = latitude - dlat;
        double maxlat = latitude + dlat;
        double minlng = longitude - dlng;
        double maxlng = longitude + dlng;

        return new String[]{dataDigitToStr(5, maxlng), dataDigitToStr(5, minlng), dataDigitToStr(5, maxlat), dataDigitToStr(5, minlat)};
    }

    public static double getDistanceOfMeter(double lng1, double lat1, double lng2, double lat2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
                + Math.cos(radLat1) * Math.cos(radLat2)
                * Math.pow(Math.sin(b / 2), 2)));
        s = s * 6378.137;
        s = Math.round(s * 10000) / 10;
        return s;
    }

    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    public static void main(String[] args) {
        System.out.println(gdConvertBd("119.73913192749026", "29.976842008144256"));
        System.out.println(bdConvertGd("120.073562", "30.295795"));
    }
}
